﻿/*
 *    Copyright © 2012 FPInst authors
 *
 *      This file is part of the FPInst project 
 *      (for more information, see: http://code.google.com/p/fpinst/).
 *
 *    FPInst is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    FPInst is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with FPInst.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Cellum.Tools;
using System.Drawing.Drawing2D;
using System.Diagnostics;

namespace RotSw
{
    public partial class RotSwControl : Control
    {

        public float pos;
        private Point temppos;

        public delegate void ValueChangeHandler(object sender, CancelEventArgs e);
        public event ValueChangeHandler ValueChanged;

        public RotSwControl()
        {
            InitializeComponent();
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            //Value = value;
        }

        public int Value
        {
            get 
            {
                /*float valrng = maxvalue - minvalue;
                float posrng = 360 * ratio / 100;
                value = (int)((pos + (posrng / 2)) * (valrng / posrng)) + minvalue;*/
                return (int)this.value; 
            }

            set 
            {
                //this.value = value;
                SetValue(value);
                this.Invalidate();
                /*float valrng = maxvalue - minvalue;
                float posrng = 360 * ratio / 100;
                pos = ((value - minvalue) / (valrng / posrng)) - (posrng / 2);*/
            }
        }

        private void SetPosition(float newpos)
        {
            float oldpos = pos;
            pos = newpos;
            int newval = Value;
            if ((newval > maxvalue) || (newval < minvalue))
                pos = oldpos;
            else
            {
                CancelEventArgs cea = new CancelEventArgs();
                if (ValueChanged != null) ValueChanged(this, cea);
                if (cea.Cancel == true)
                    pos = oldpos;
            }
        }

        private void SetValue(float newval)
        {
            if (newval > maxvalue) newval = maxvalue;
            if (newval < minvalue) newval = minvalue;
            if (newval == value) return;

            float oldval = value;
            value = newval;

            CancelEventArgs cea = new CancelEventArgs();
            if (ValueChanged != null) ValueChanged(this, cea);
            if (cea.Cancel == true)
                value = oldval;

            float valrng = maxvalue - minvalue;
            float posrng = 360 * ratio / 100;
            pos = ((value - minvalue) / (valrng / posrng)) - (posrng / 2);
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            int x = this.Size.Width / 2;
            int y = this.Size.Height / 2;

            int radius = (x > y) ? y : x;
            radius = radius - 5;

            GraphicsPath gp = GraphicsHelper.GetHandle(this.Size.Width / 2, this.Size.Height / 2, radius, grippetals, pos, (float)(Math.PI / 20), gripthickness);
            Rectangle r = new Rectangle(0, 0, x*2, y*2);

            LinearGradientBrush brush = new LinearGradientBrush(r, gripdarkcolor, griplightcolor, lightangle, false);
            LinearGradientBrush topbrush = new LinearGradientBrush(r, topdarkcolor, toplightcolor, lightangle, false);
            LinearGradientBrush markerbrush = new LinearGradientBrush(r, markdarkcolor, marklightcolor, lightangle, false);

            pe.Graphics.FillPath(brush, gp);

            int topradius = radius - gripthickness;
            pe.Graphics.FillCircle(topbrush, x, y, topradius*2);
            pe.Graphics.FillPolygon(markerbrush, GraphicsHelper.GetMarker(x, y, radius - gripthickness, pos, marklength, markwidth));

        }

        public void Wheel(int delta) 
        {
            int mul = Control.ModifierKeys == Keys.Control ? stepsmall : (Control.ModifierKeys == Keys.Shift ? stepbig : step);
            //SetPosition( pos + delta / 120f * mul);
            SetValue(value + delta / 120f * mul);
            Debug.WriteLine("pos:" + pos);
            this.Invalidate();
        }

        //protected override void OnMouseWheel(MouseEventArgs e)
        //{
        //    int mul = Control.ModifierKeys == Keys.Control ? 1 : 10;
        //    pos += e.Delta / 120 * mul;
        //    this.Invalidate();
        //    base.OnMouseWheel(e);
        //}

        protected override void OnMouseEnter(EventArgs e)
        {
            MouseMessageFilter.ActualControl = this;
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            MouseMessageFilter.ActualControl = null;
            base.OnMouseLeave(e);
        }

        protected override void  OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Capture = true;
                temppos = Cursor.Position;
            }
 	        else base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Capture = false;
            }
            else base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (this.Capture == true)
            {
                int mul = Control.ModifierKeys == Keys.Control ? stepsmall : (Control.ModifierKeys == Keys.Shift ? stepbig : step);
                int delta = (Cursor.Position.X - temppos.X) + (temppos.Y - Cursor.Position.Y);
                temppos = Cursor.Position;
                //SetPosition(pos + delta * mul);
                SetValue(value + delta * mul);
                Debug.WriteLine("pos:" + pos + " | value: " + Value);
                this.Invalidate();
            }
            else base.OnMouseMove(e);
        }
    }
}
